package com.sunwayworld.basemodule.common.utils;

import com.sunwayworld.framework.support.tree.TreeDescriptor;
import com.sunwayworld.framework.support.tree.bean.AbstractTreeNode;
import com.sunwayworld.framework.utils.ClassUtils;
import com.sunwayworld.framework.utils.CollectionUtils;
import com.sunwayworld.framework.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;

public abstract class LimsTreeHelper {

    private static final Logger log = LoggerFactory.getLogger(LimsTreeHelper.class);

    public LimsTreeHelper() {
    }

    public static final <T, R extends AbstractTreeNode> List<R> parseTreeNode(List<T> treeItemList, TreeDescriptor<T> descriptor, Class<R> treeNodeClass) {
        if (treeItemList.isEmpty()) {
            return CollectionUtils.emptyList();
        }

        // Mybatis查询数据时的结果集是unmodifiable，所以这里要重新生成一个List
        List<T> cloneTreeItemList = new ArrayList<>();
        cloneTreeItemList.addAll(treeItemList);

        // 转换成TreeNode
        @SuppressWarnings("unchecked")
        List<R> sortedNodeList = cloneTreeItemList.stream().map(t -> {
            R node = null;

            if (descriptor.getParseTreeNodeFunction() != null) {
                node = (R) descriptor.getParseTreeNodeFunction().apply(t);
            } else {
                node = ClassUtils.newInstance(treeNodeClass);
                // 使用原生的BeanUtils
                BeanUtils.copyProperties(t, node);
            }

            String id = descriptor.getParseTreeNodeIdFunc().apply(t);
            node.setId(id);
            if (descriptor.getParseTreeNodeParentIdFunc() != null) {
                node.setParentId(descriptor.getParseTreeNodeParentIdFunc().apply(t));
            }
            node.setText(descriptor.getParseTreeNodeTextFunction().apply(t));

            for (BiConsumer<T, AbstractTreeNode> consumer : descriptor.getConsumerList()) {
                consumer.accept(t, node);
            }

            return node;
        }).collect(Collectors.toList());

        List<R> sortedRootNodeList = new ArrayList<>();

        if (descriptor.getParseTreeNodeParentIdFunc() != null) { // 字段里有父类编码

            sortedNodeList.sort((r1, r2) -> {
                if (r1.getId().equals(r2.getParentId())) {
                    return -1;
                }
                if (r2.getId().equals(r1.getParentId())) {
                    return 1;
                }
                return 0;
            });
            // 减少循环遍历次数
            Map<String, List<R>> nodeMaps = sortedNodeList.stream().collect(Collectors.groupingBy(R::getParentId));
            for (String parentId : nodeMaps.keySet()) {
                boolean hasParent = false;
                List<R> nodes = nodeMaps.get(parentId);

                // 遍历查询父节点
                for (R innerLoopNode : sortedNodeList) {
                    if (innerLoopNode.getId().equals(parentId)) { // 父节点
                        if (innerLoopNode.getLvl() == null) {
                            innerLoopNode.setLvl(1); // 层级
                        }
                        for (R node : nodes) {
                            innerLoopNode.addChild(node);
                            node.setLvl(innerLoopNode.getLvl() + 1);
                        }
                        hasParent = true;
                        break;
                    }
                }

                if (!hasParent) { // 不存在父节点
                    for (R node : nodes) {
                        if (node.getLvl() == null) {
                            node.setLvl(1); // 层级
                        }
                    }
                    sortedRootNodeList.addAll(nodes);
                }
            }

        } else {
            for (R node : sortedNodeList) {
                int nodeLength = node.getId().length();

                R parentNode = null;

                // 遍历查询父节点
                for (R innerLoopNode : sortedNodeList) {
                    int innerLoopNodeLength = innerLoopNode.getId().length();

                    if (nodeLength > innerLoopNodeLength && StringUtils.startsWith(node.getId(), innerLoopNode.getId())) {
                        // 层次码长度最大的为仅跟着的父节点
                        if (parentNode == null || innerLoopNodeLength > parentNode.getId().length()) {
                            parentNode = innerLoopNode;
                        }
                    }
                }

                if (parentNode == null) { // 不存在父节点
                    if (node.getLvl() == null) {
                        node.setLvl(1); // 层级
                    }
                    sortedRootNodeList.add(node);
                } else { // 存在父节点，存入父节点的子节点列表中
                    if (parentNode.getLvl() == null) {
                        parentNode.setLvl(1); // 层级
                    }
                    parentNode.addChild(node);
                    node.setLvl(parentNode.getLvl() + 1);
                    node.setParentId(parentNode.getId());
                }
            }
        }

        return sortedRootNodeList;
    }

}
